/*
	Copyright (C) 2010 Salil Bhagurkar

	This file is part of k3

	k3 is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	k3 is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with k3.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <shared.h>


struct link_status {
	struct buffer *link;
	struct fs *fs;
};


static int vmdrvlink_write(struct fs *referrer, struct fs *this, struct buffer *buf, u32 offset, u32 count)
{
	//Check if there is any data on us.
	if(!(this->buf.data)) {
		//Get a string from the buffer to call fsparse functions
		char *path = buffer_to_string(buf);
		dprint(D_INFO, this->name, "Set link to %s", path);
		//Make a link_status structure
		struct link_status *ls;
		struct fs *dest_fs = fsparse_get_relative(referrer, path);
		if(!dest_fs) {
			dprint(D_ALERT, this->name, "Could not find %s relative to %s", path, referrer);
			return ESTATEINV;
		}
		ls = (struct link_status *)malloc_get(sizeof(struct link_status), "vlink");
		ls->link = buf;
		ls->link = buffer_duplicate(buf);
		ls->fs = dest_fs;
		this->buf.data = ls;
		this->buf.len = sizeof(struct link_status);
		this->buf.alloc_len = this->buf.len;
		//Free the string we got
		malloc_free(path);
		return 0;
	} else {
		//Redirect to link
		struct link_status *ls = this->buf.data;
		return fs_write(referrer, ls->fs, buf, offset, count);
	}
}

static int vmdrvlink_read(struct fs *referrer, struct fs *this, struct buffer *buf, u32 offset, u32 count)
{
	//Simply redirect to linked node
	struct link_status *ls = this->buf.data;
	if(!ls) {
		dprint(D_ALERT, this->name, "No link to read from");
		return ESTATEINV;
	}
	return fs_read(referrer, ls->fs, buf, offset, count);
}


int vmdrvlink_init()
{
	dprint(D_PROG, "link", "Initialize vmdrv");
	struct fs *fs = fs_create(FSFLAGS_VMDRV, "link");
	fs->system = fs_create_system(0, vmdrvlink_read, vmdrvlink_write, dummy, fs);
	fs_link(fsparse_get("/vmdrv"), fs);
	return 0;
}
